iT邦幫忙

第 11 屆 iThome 鐵人賽

7

今天要介紹的是在 Line Bot 加入圖文選單,那什麼是圖文選單呢?
下方紅框的部分就是圖文選單。

https://ithelp.ithome.com.tw/upload/images/20191216/20106865YSTH7HQqyY.jpg

圖文選單的主要用途如下:

  • 讓第一次使用的人快速了解 Bot 的功能
  • 將 Bot 功能寫在按鈕方便使用者操作
  • 放廣告或最新消息做品牌行銷

要建立圖文選單有兩種方式,第一種進入 Line@ 後台有功能可以使用,第二種透過 Postman 等軟體或寫程式呼叫 API。

雖然下面要介紹的是 API,不過不是因為 "身為工程師當然是要寫程式" 這個原因,我其實很想用功能,沒用的原因是我以為後台建立圖文選單的功能需要收費,小弟口袋不深只好選擇 API,不過最近查資料發現此功能已經變成免費的,可以安心服用了。

2019/4/18 後只要升級官方帳號 2.0 就可以免費使用

既然功能都免費了,當然要用好用滿,不過這篇還是以介紹 API 為主,後台編輯功能可以參考這篇文章,連結: 【功能介紹】圖文影音內容 - 圖文選單 - 電腦版


建立圖文選單

建立 Line Bot 圖文選單需要 Line Bot 的 channel access token,還沒有建立 Line Bot 的讀者可以參考第一篇 [Day01] LINE Bot 帳號申請

這裡會使用 Postman 呼叫 API,Postman 網址。

建立圖文選單有三個步驟:

  1. 建立圖文選單
  2. 上傳圖文選單的圖片
  3. 設定預設的圖文選單

1. 建立圖文選單

POST https://api.line.me/v2/bot/richmenu

Request headers

Authorization: Bearer {channel access token}
Content-Type: application/json

Request body

{
    "size": {
      "width": 2500,
      "height": 843
    },
    "selected": false,
    "name": "richmenu-1",
    "chatBarText": "選單1",
    "areas": [
      {
        "bounds": {
          "x": 0,
          "y": 0,
          "width": 833,
          "height": 843
        },
        "action": {
          "type": "message",
          "label": "文字",
          "text": "Hello, iBot!"
        }
      },
      {
        "bounds": {
          "x": 833,
          "y": 0,
          "width": 833,
          "height": 843
        },
        "action": {
          "type": "uri",
          "label": "網址",
          "uri": "https://ithelp.ithome.com.tw/users/20106865/ironman/2732"
        }
      },
      {
        "bounds": {
          "x": 1666,
          "y": 0,
          "width": 833,
          "height": 843
        },
        "action": {
          "type": "postback",
          "label": "選單2",
          "data": "action=changeMenu2"
        }
      }
   ]
}

Response

{
    "richMenuId": "{rich menu id}"
}

這裡稍微解釋一下 API 的用法,詳細說明可以參考官方文件

第一個區塊是 API 的網址,需要使用 POST 方法呼叫

第二區塊是 header 的參數,{channel access token} 要替換成自己申請 Line Bot 時的那個 token,application/json 表示下方 Request body 的格式為 json

第三區塊為 http 的主體,用來定義圖文選單相關的設定

  • size: 圖文選單圖片的長寬,必需為以下尺寸:
    2500x1686、2500x843、1200x810、1200x405、800x540、800x270

  • selected: 選單是否預設開啟,這裡我設定為 false,預設不開啟。

  • name: 選單名稱,用於識別和管理選單,不會顯示給使用者。

  • chatBarText: 顯示在聊天視窗下方的選單文字。

  • areas: 用於定義按鈕的可點墼區域。

    • bounds 用於定義座標和大小

      • x、y: 起始座標

      • width: 寬度

      • height: 高度

    • action 用於定義觸發的動作

      • type: 動作類型,詳細說明可以參考 官方文件

      • label: 動作標籤,用於客戶端輔助功能

      • text: 發送到聊天視窗的文字

      • data: 透過 webhook 回傳到後端的字串

第四區塊為回傳訊息,選單建立成功後會回傳 {rich menu id} 後面 API 會使用到。

Postman 結果

  • Header 部分

https://ithelp.ithome.com.tw/upload/images/20191216/20106865CkXvzBj6iD.jpg

  • Body 部分

https://ithelp.ithome.com.tw/upload/images/20191216/201068657ZKXJHj1pf.jpg


2. 上傳圖文選單的圖片

POST https://api.line.me/v2/bot/richmenu/{rich menu id}/content

[Request headers]
-----------------
Authorization: Bearer {channel access token}
Content-Type: image/jpeg or image/png
Content-Length: request body 大小 (byte)

[Request body]
--------------
圖片主體
格式: JPEG 或 PNG
長寬: 2500x1686, 2500x843, 1200x810, 1200x405, 800x540, 800x270
大小限制: 1 MB

[Response]
----------
{}

將第一步得到的 {rich menu id} 帶入網址,接著 Body 部分選擇 binary 可以選擇圖片,最後按送出,這個步驟比較簡單,成功會回傳 JSON 空物件。

Postman 結果

  • Header 部分

Content-Length 好像可以省略,怕算錯乾脆不要了 (╯‵□′)╯︵┻━┻

https://ithelp.ithome.com.tw/upload/images/20191216/20106865IAMo23I9pa.jpg

  • Body 部分

https://ithelp.ithome.com.tw/upload/images/20191216/201068655dJLezWOOD.jpg


3. 設定預設的圖文選單

POST https://api.line.me/v2/bot/user/all/richmenu/{rich menu id}

[Request headers]
Authorization: Bearer {channel access token}

[Request body]
無

[Response]
{}

這步驟會設定所有用戶預設看到的圖文選單,還有另一個 API 可以單獨設定某位用戶的選單,後面介紹動態選單的時候會用到。

Postman 結果

  • Header 部分

https://ithelp.ithome.com.tw/upload/images/20191216/20106865JFHqXW0ZFF.jpg


結果

https://ithelp.ithome.com.tw/upload/images/20191216/20106865iudV2vWTJr.jpg

。:.゚ヽ(*´∀`)ノ゚.:。


HTML 轉圖片

因為對 Photoshop 不熟,這裡我用 HTML + Font Awesome 把樣子排出來,再用 JS 套件將 HTML 轉成圖片,用於製作陽春的選單還蠻方便的。

JSFiddle

HTML

<table>
  <tr>
    <td id="block1">
      <i class="fa fa-file-text-o icon"></i>
      <div class="text">文字</div>
    </td>
    <td id="block2">
      <i class="fa fa-link icon"></i>
      <div class="text">網址</div>
    </td>
    <td id="block3">
      <i class="fa fa-list icon"></i>
      <div class="text">選單</div>
    </td>
  </tr>
</table>

<div style="margin-top: 10px">
  <input type="button" id="btn" value="另存圖片"/>
</div>

<div id="img"></div>

CSS

table {
  width: 2500px;
  height: 843px;
  border-collapse: collapse;
  font-family: Microsoft JhengHei;
}

table td {
  text-align: center;
  padding: 0px;
}

.icon {
  color: #ffffff;
  font-size: 280px;
}

.text {
  margin-top: 10px;
  color: #ffffff;
  font-size: 120px;
  font-weight: bold;
}

#block1 {
  background-color: #00D084;
  width: 33.33%;
}

#block2 {
  background-color: #2D8665;
  width: 33.33%;
}

#block3 {
  background-color: #00D084;
  width: 33.33%;
}

JS

$(function() { 
    $("#btn").click(function() { 
        html2canvas($("table"), {
            onrendered: function(canvas) {
                $("#img").append(canvas);
                $('#img canvas').css('max-width', '600px');
            }
        });
    });
}); 

色碼

JSFiddle


官方資源下載專區

官方也有許多不錯的資源供大家下載,可以進去挖寶。

https://events.line.me/tw/lineat/minisite/wp-content/themes/line/download.php


動態圖文選單

最後要介紹的是動態選單,什麼是動態選單?

這裡的動態是指,利用 設定的個別用戶選單 這個 API,讓 Line Bot 可以個別切換某位使用者的選單,用途如下。

  • 製作階層選單
  • 擴充圖文選單按紐 (可以超過6個)
  • 為特定族群或使用者客制選單

接下來會實作一個兩層的選單,使用者可以透過上下頁按紐切換。

切換邏輯會利用 API 的優先順序特性,例如: 按下一頁時,程式會將 個別用戶選單 設定為 選單2,因為 個別優先於預設 選單就會切換,而按上一頁時,程式將 個別用戶選單 移除,選單就會切換回去,這裡也可以不用移除,將 個別用戶選單 設定為 選單1 也可以。

圖文選單顯示的優先順序(高到低):

  1. 使用 Messaging API 設定的個別用戶選單
  2. 使用 Messaging API 設定的預設選單
  3. 使用 LINE Official Account Manager 設定的預設選單

製作選單

照上面介紹的方法製作兩個選單。

選單1

"action": {
  "type": "postback",
  "label": "下一頁",
  "data": "action=next"
}

https://ithelp.ithome.com.tw/upload/images/20191216/20106865EH68Efbcho.jpg

選單2

"action": {
  "type": "postback",
  "label": "上一頁",
  "data": "action=prev"
}

https://ithelp.ithome.com.tw/upload/images/20191216/20106865n9xZF7YQ6H.jpg

Postback

可以看到按鈕的 action 我使用了 postback 類型,這個類型會在使用者點擊按紐時,透過 Webhook 呼叫後端的程式,且不會有文字出現在聊天視窗上。

另外還可以使用像 QueryString 一樣的方式附帶參數,例如上方我使用 next 和 prev 分別代表兩個按鈕動作,後端收到後就可以以此去執行各自的程式。

不過電腦版的 LINE 看不到圖文選單,這時就只能用文字控制 line Bot 功能,因此各有其優缺點,但如果單看圖文選單,比起文字類型會更推薦使用 Postback。

使用 LineMessagingApi 切換圖文選單

開啟 LineBotApp.cs 加入下面程式。

protected override async Task OnPostbackAsync(PostbackEvent ev)
{
    var query = HttpUtility.ParseQueryString(ev.Postback.Data);

    //頻道Id
    var channelId = ev.Source.Id;
    //使用者Id
    var userId = ev.Source.UserId;

    switch (query["action"])
    {
        //下一頁
        case "next":
            {
                //設定個別用戶選單
                await _messagingClient.LinkRichMenuToUserAsync(userId, "選單2 的Id");
            }
            break;
        //上一頁
        case "prev":
            {
                //移除個別用戶選單
                await _messagingClient.UnLinkRichMenuFromUserAsync(userId);
            }
            break;
    }
}

完整 LineBotApp.cs 可以參考:
[Day02] 使用 .NET Core 3.0 + LineMessagingApi 串接 Line Bot

結果

預設選單

https://ithelp.ithome.com.tw/upload/images/20191216/20106865A81Z42MYz3.jpg

點下一頁會跳到選單2,點上一頁又會返回

https://ithelp.ithome.com.tw/upload/images/20191216/20106865fKyFi7hkXP.jpg


[C#] 建立圖文選單 - LineMessagingApi 用法

這邊是筆記,將上面使用 Postman 的地方改成 C#。

  • 建立圖文選單
var richMenu = new RichMenu()
{
    Size = new ImagemapSize(2500, 843),
    Selected = false,
    Name = "richmenu-1",
    ChatBarText = "選單1",
    Areas = new List<ActionArea>()
    {
        new ActionArea()
        {
            Bounds = new ImagemapArea(0, 0 ,833, 843),
            Action = new MessageTemplateAction("文字", "Hello, iBot!")
        },
        new ActionArea()
        {
            Bounds = new ImagemapArea(833, 0 ,833, 843),
            Action = new UriTemplateAction("網址", "https://ithelp.ithome.com.tw/users/20106865/ironman/2732")
        },
        new ActionArea()
        {
            Bounds = new ImagemapArea(1666, 0 ,833, 843),
            Action = new PostbackTemplateAction("選單2", "action=changeMenu2")
        }
    }
};
var richMenuId = await _messagingClient.CreateRichMenuAsyn(richMenu);
  • 上傳圖文選單的圖片
var image = new MemoryStream(File.ReadAllBytes(@"richmenu.png"));
await _messagingClient.UploadRichMenuPngImageAsync(image, richMenuId);
  • 設定預設的圖文選單
await _messagingClient.SetDefaultRichMenuAsync(richMenuId);

其他相關 API

詳細內容可參考 官方文件

  • 查詢所有圖文選單
GET https://api.line.me/v2/bot/richmenu/list

[Request headers]
Authorization: Bearer {channel access token}

[Response]
JSON 格式的列表清單
  • 刪除圖文選單
DELETE https://api.line.me/v2/bot/richmenu/{rich menu id}

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}
  • 取得預設的圖文選單
GET https://api.line.me/v2/bot/user/all/richmenu

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{
    "richMenuId": "{rich menu id}"
}
  • 取消預設的圖文選單
DELETE https://api.line.me/v2/bot/user/all/richmenu

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

結語

這篇本來沒準備寫這麼長,沒想到資料越找越多,還意外發現動態選單的用法,手癢就自己實做了一次。最後的切換選單功能,用起來其實有點卡卡的,會延遲個1~2秒,在可以接受的範圍拉,選單功能如果不需要頻繁切換,總體來說還是不錯的。

在過程中還看到一位大大的鐵人文 LINE bot 好好玩 30 天玩轉 LINE API
這位大大把 LINE 可以玩的 API 都試過了一次,我這才知道原來 LINE API 可以玩的東西這麼多,LINE 真是越來越強大了,有興趣的朋友可以去看他的鐵人文。

下一篇要將 Line Bot 結合資料庫,內容會介紹如何在 Azure 的 App Service 開啟 MySql 資料庫,並且會搭配 Entity Framework 使用,會教大家建立 Model 並透過 Fluent API 設定資料表的屬性和關聯。

最後會實做出一個完整的功能,目前規劃是可以透過 Line Bot 訂閱某人 it 邦的首頁,程式會透過爬蟲每天去取得文章的觀看數,接著可以透過 Line Bot 查詢每日、每周、每月,前5名,點閱數增加最多的文章。

今天就到這,感謝大家觀看~~~

參考文章

用LINE bot api建立line@圖文選單
如何建立LineBot圖文選單
Linebot-Demo-DynamicRichMenu
Messaging API reference
Using rich menus


上一篇
[Day05] 在 LINE Bot 加入 LUIS 語意分析服務
下一篇
[Day07] 使用 EF Core 讀取 Azure 上的 MySQL 資料庫
系列文
Line Bot 心得分享 LineMessagingApi + LUIS + BotFramework 共 27 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3
cathywen14
iT邦新手 4 級 ‧ 2019-12-18 15:28:56

居然連選單功能都做了!! 推推~

一定要的啊 〜( ̄▽ ̄〜) (〜 ̄▽ ̄)〜

1
eric19740521
iT邦新手 1 級 ‧ 2020-01-06 13:40:30

讚喔!!!用得上,很棒的文章

謝謝 ╰( ̄▽ ̄)╭

感謝你提供的工具
http://ezpos.info/linebot/%E4%B8%8B%E8%BC%89%20(4).png

/images/emoticon/emoticon12.gif

0
yicheng0615
iT邦新手 5 級 ‧ 2020-07-16 15:29:14

請問可以做postman製作子選單的詳細教學嗎?遇到瓶頸了看不懂

看更多先前的回應...收起先前的回應...

首先使用文中介紹的方式建立兩個圖文選單
接著將第一個選單設為預設選單

POST https://api.line.me/v2/bot/user/all/richmenu/{richMenuId_1}

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

然後就可以使用下面的 API 切換選單

下一頁:

設定 User 的 Rich Menu

POST 
https://api.line.me/v2/bot/user/{userId}/richmenu/{richMenuId_2}

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

上一頁:

取消 User 的 Rich Menu

DELETE https://api.line.me/v2/bot/user/{userId}/richmenu

[Request headers]
Authorization: Bearer {channel access token}

[Response]
{}

這個是不是不能用python呀?

user id是line developers裡面的user id嗎?
我製作好2個選單,下一頁跟上一頁也都弄好了
但我不是很明白 "然後就可以使用下面的 API 切換選單"這一句
不好意思我第一次學習,很多地方不懂

Python 我使用這個 SDK。
https://github.com/line/line-bot-sdk-python

@handler.add(PostbackEvent)
def handle_postback(event):
    # postback 資料
    data = event.postback.data
    # 使用者Id
    userId = event.source.user_id
    
    # 下一頁
    if data == "action=next":
        # 設定個別用戶選單
        line_bot_api.link_rich_menu_to_user(userId, <rich_menu_id>)
    # 上一頁
    elif data == "action=prev":
        # 移除個別用戶選單
        line_bot_api.unlink_rich_menu_from_user(userId)

1.user id是line developers裡面的user id嗎?

不是喔,是 Message API 傳給我們的使用者Id

2.但我不是很明白 "然後就可以使用下面的 API 切換選單"這一句

下面兩個 API 可以讓不同使用者看到不同的選單
切換選單就是運用這兩個 API 達成的
不過一般不會直接拿來使用
會向上面的程式一樣
使用官方包裝好的 SDK

所以我是要在我的程式碼加上上面那一段嗎?
然後postman不用更動的意思嗎?
那上面的程式碼哪些是我要改的呀

恩恩,Postman 只要做 建立選單 和 設定預設選單 就好
子選單切換需要用程式

那上面的程式碼哪些是我要改的呀

不知道你目前的寫法,無法給建議

所以上一頁跟下一頁那個也做出來就好不用動對嗎?
https://ithelp.ithome.com.tw/upload/images/20200721/20128656A8XZTALcov.png
目前只有最基本的東西,將程式與linebot做結合而已

將上面的程式直接加入 callback 下方就可以
<rich_menu_id> 的部分替換成第二選單的 id
不過我沒有測過,你要試試看

加進去了,但還是沒反應,不知道為什麼...

user id 是這邊個嗎
https://ithelp.ithome.com.tw/upload/images/20200723/20128656H8M51CGpwv.png

可以了,感謝你

用程式取得的 userId 才能符合所有使用者喔

# 使用者Id
userId = event.source.user_id
0
KLXTaro
iT邦新手 5 級 ‧ 2020-10-01 00:20:13

博主您好,想請問我的postman設定是不是有問題?,一直報cors error的錯orzhttps://ithelp.ithome.com.tw/upload/images/20201001/20117685v0oTQvZuE1.jpg

網頁版的 Postman 有跨域限制 (這是瀏覽器本身的安全機制)
可以改用桌面板或 Chrome 擴充版
/images/emoticon/emoticon12.gif

KLXTaro iT邦新手 5 級 ‧ 2020-10-02 20:14:11 檢舉

謝謝你的教學,我成功了✧*。٩(ˊᗜˋ*)و✧*

/images/emoticon/emoticon12.gif

0
cloudyang
iT邦新手 5 級 ‧ 2021-07-06 22:27:53

想請問,我的line bot後端是架在heroku,若我想做出動態圖文選單,那麼LineBotApp.cs要怎麼加上去執行呢?
https://ithelp.ithome.com.tw/upload/images/20210706/20139237HvF45iK9gY.png

看更多先前的回應...收起先前的回應...

原程式是 Python 的話,感覺改成 Python 比較快 ?

SDK:
https://github.com/line/line-bot-sdk-python

@handler.add(PostbackEvent)
def handle_postback(event):
    # postback 資料
    data = event.postback.data
    # 使用者Id
    userId = event.source.user_id
    
    # 下一頁
    if data == "action=next":
        # 設定個別用戶選單
        line_bot_api.link_rich_menu_to_user(userId, <rich_menu_id>)
    # 上一頁
    elif data == "action=prev":
        # 移除個別用戶選單
        line_bot_api.unlink_rich_menu_from_user(userId)
cloudyang iT邦新手 5 級 ‧ 2021-07-07 11:34:10 檢舉

哇!太感謝啦/images/emoticon/emoticon02.gif

cloudyang iT邦新手 5 級 ‧ 2021-07-07 12:30:14 檢舉

有成功了,在改改圖片就好,真的非常謝謝您

/images/emoticon/emoticon12.gif /images/emoticon/emoticon12.gif /images/emoticon/emoticon12.gif

0
arguskao
iT邦新手 3 級 ‧ 2022-06-09 21:27:30

官方資源下載專區

連結好像失效?

恩失效了,不過時間太久,我也忘記內容是什麼了

我要留言

立即登入留言